Micron Document
๐ŸŽ–๏ธGitะฏั€ะฐ๐ŸŽ–๏ธ


Displaying Raw โ€ข Download

core/repository/src/commonMain/kotlin/org/meshtastic/core/repository/RadioInterfaceService.kt 2d20cd8a4708e2ef66e98d5259f3a97ec93f240a (2d20cd8a) Text, 11.34 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.repository

Tff7b72import T7ee787kotlinx.coroutines.CoroutineScope
Tff7b72import T7ee787kotlinx.coroutines.flow.Flow
Tff7b72import T7ee787kotlinx.coroutines.flow.StateFlow
Tff7b72import T7ee787org.meshtastic.core.model.ConnectionState
Tff7b72import T7ee787org.meshtastic.core.model.DeviceType
Tff7b72import T7ee787org.meshtastic.core.model.InterfaceId
Tff7b72import T7ee787org.meshtastic.core.model.MeshActivity

T8b949e/** A lifecycle lease held by one already-admitted operation for [session]. */
Tff7b72interface T56d364RadioSessionLease Tb4b4b4{
Tff7b72val Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContext

T8b949e/** True until this admitted operation releases the session and rollover may complete. */
Tff7b72fun Td2a8ffisCurrentTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean
Tb4b4b4}

T8b949e/** Owns admission and revocation for work bound to one transport session. */
Tff7b72interface T56d364RadioSessionAuthority Tb4b4b4{
T8b949e/**
* The transport session that still owns lifecycle completion, or null after teardown drains every admitted
* operation. Implementations close admission before teardown, so [isSessionActive] and the run helpers reject new
* work immediately even while this flow temporarily retains the draining session.
*/
Tff7b72val Te6edf3activeSessionTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3RadioSessionContext?Tff7b72>

T8b949e/**
* Returns whether [session] still owns transport admission. Implementations must make this reflect the admission
* gate, not only [activeSession], because the draining session may remain published after new work is rejected.
*/
Tff7b72fun Td2a8ffisSessionActiveTb4b4b4(Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContextTb4b4b4)Tb4b4b4: Tffa657Boolean

T8b949e/**
* Runs [block] only while [session] owns transport admission. Implementations must make the admission check and
* synchronous side effect atomic with teardown.
*/
Tff7b72fun Td2a8ffrunIfSessionActiveTb4b4b4(Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContextTb4b4b4, Te6edf3blockTb4b4b4: Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tb4b4b4: Tffa657Boolean

T8b949e/**
* Acquires a lifecycle lease for suspend [block]. Once admitted, teardown closes admission to later work and waits
* for this block to finish before publishing session completion or starting a replacement transport. [block] may
* use [RadioSessionLease.isCurrent] for transaction-bound checks that must remain valid through commit even after
* teardown has closed new admission. Implementations must acquire and release the lease through the same admission
* state used by teardown; comparing only [activeSession] cannot satisfy the draining contract. Callers must keep
* the block bounded and must not invoke transport lifecycle methods from inside it.
*/
Tff7b72suspend Tff7b72fun Td2a8ffrunWithSessionLeaseTb4b4b4(Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContextTb4b4b4, Te6edf3blockTb4b4b4: Te6edf3suspend Tb4b4b4(Te6edf3RadioSessionLeaseTb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tb4b4b4: Tffa657Boolean

T8b949e/**
* Runs [block] while holding the same lifecycle lease, without exposing the lease token. Implementations may
* serialize this convenience path to preserve handshake ordering; independently deferred work should use
* [runWithSessionLease] so it can acquire its own lease before its parent operation returns.
*/
Tff7b72suspend Tff7b72fun Td2a8ffrunWhileSessionActiveTb4b4b4(Te6edf3sessionTb4b4b4: Te6edf3RadioSessionContextTb4b4b4, Te6edf3blockTb4b4b4: Te6edf3suspend Tb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657UnitTb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72=
Te6edf3runWithSessionLeaseTb4b4b4(Te6edf3sessionTb4b4b4) Tb4b4b4{ Te6edf3blockTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4}

T8b949e/**
* Interface for the low-level radio interface that handles raw byte communication.
*
* This is the **transport layer** โ€” it manages the raw hardware connection (BLE, TCP, Serial, USB) to a Meshtastic
* radio. Its [connectionState] reflects whether the physical link is up or down, **before** any handshake or
* config-loading logic is applied.
*
* **Important:** UI and feature modules should **never** observe [connectionState] directly. Instead, they should use
* [ServiceRepository.connectionState], which is the canonical app-level connection state that accounts for handshake
* progress, light-sleep policy, and other higher-level concerns. The only legitimate consumer of this transport-level
* flow is [MeshConnectionManager], which bridges transport state changes into the app-level
* [ServiceRepository.connectionState].
*
* @see ServiceRepository.connectionState
*/
Tff7b72interface T56d364RadioInterfaceService Tb4b4b4:
Te6edf3RadioTransportCallbackTb4b4b4,
Te6edf3RadioSessionAuthority Tb4b4b4{
T8b949e/** The device types supported by this platform's radio interface. */
Tff7b72val Te6edf3supportedDeviceTypesTb4b4b4: Te6edf3ListTff7b72<Te6edf3DeviceTypeTff7b72>

T8b949e/**
* Transport-level connection state of the radio hardware.
*
* This flow reflects the raw state of the physical link (BLE, TCP, Serial, USB):
* - [ConnectionState.Connected] โ€” the transport link is established
* - [ConnectionState.Disconnected] โ€” the transport link is down (permanent)
* - [ConnectionState.DeviceSleep] โ€” the transport link is down (transient, device sleeping)
*
* **This is NOT the canonical app-level connection state.** The transport may report [ConnectionState.Connected]
* while the app is still performing the mesh handshake (config + node-info exchange), during which the app-level
* state remains [ConnectionState.Connecting].
*
* Only [MeshConnectionManager] should observe this flow. All other consumers (ViewModels, feature modules, UI) must
* use [ServiceRepository.connectionState].
*
* @see ServiceRepository.connectionState
*/
Tff7b72val Te6edf3connectionStateTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ConnectionStateTff7b72>

T8b949e/** Flow of the current device address. */
Tff7b72val Te6edf3currentDeviceAddressFlowTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657String?Tff7b72>

T8b949e/**
* Monotonically increasing generation bumped on every transport start (including same-address reconnect). Consumers
* use this to discard state retained from a previous transport instance. Stub implementations that never start a
* real transport expose a constant zero flow.
*/
Tff7b72val Te6edf3sessionGenerationTb4b4b4: Te6edf3StateFlowTff7b72<Tffa657LongTff7b72>

T8b949e/** Whether we are currently using a mock transport. */
Tff7b72fun Td2a8ffisMockTransportTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean

T8b949e/**
* Flow of raw data received from the radio, bound to the transport session that admitted each frame.
*
* Emissions preserve the order in which bytes arrived from the hardware โ€” this is required because the firmware
* handshake (initial config packet ordering) depends on strict FIFO delivery. Implementations MUST guarantee
* ordering; do not swap in a [SharedFlow] without preserving order.
*/
Tff7b72val Te6edf3receivedDataTb4b4b4: Te6edf3FlowTff7b72<Te6edf3ReceivedRadioFrameTff7b72>

T8b949e/** Flow of radio activity events. */
Tff7b72val Te6edf3meshActivityTb4b4b4: Te6edf3FlowTff7b72<Te6edf3MeshActivityTff7b72>

T8b949e/**
* Drains any bytes currently buffered in [receivedData] without emitting them to collectors.
*
* Callers invoke this before attaching a fresh collector after a stop/start cycle so stale bytes buffered while no
* collector was attached do not get replayed ahead of the next session's handshake.
*/
Tff7b72fun Td2a8ffresetReceivedBufferTb4b4b4(Tb4b4b4)

T8b949e/** Sends a raw byte array to the radio. */
Tff7b72fun Td2a8ffsendToRadioTb4b4b4(Te6edf3bytesTb4b4b4: Te6edf3ByteArrayTb4b4b4)

T8b949e/** Initiates the connection to the radio. */
Tff7b72fun Td2a8ffconnectTb4b4b4(Tb4b4b4)

T8b949e/**
* Explicitly tears down the active transport, sending a polite `ToRadio(disconnect = true)` goodbye frame first
* when a transport is live. Safe to call when nothing is connected โ€” implementations must no-op in that case.
* Suspends until the teardown completes.
*/
Tff7b72suspend Tff7b72fun Td2a8ffdisconnectTb4b4b4(Tb4b4b4)

T8b949e/**
* Silent in-place transport restart for handshake stalls: tears down the active transport and re-establishes it in
* place, without touching the connection-request gate or the selected device address.
*
* Both transport families use this recovery path but with different trigger timings: TCP/USB reach it through the
* fast-path watchdog (~12s after the last meaningful handshake packet), while BLE reaches it after the
* retry-exhausted path (~30s/60s watchdog plus a ~15s retry window). In both cases the symptom is identical: the
* transport itself may still be physically [ConnectionState.Connected] (e.g. a TCP socket whose radio firmware has
* stopped responding to `want_config_id`, or a BLE link whose GATT peer has stalled), so flipping app-level state
* to [ConnectionState.Disconnected] alone leaves a split-brain: transport Connected + `connectionRequested=true` +
* a live `RadioTransport` handle, which then blocks same-node reconnect via [setDeviceAddress]'s fast-path. This
* method breaks that deadlock by cycling the transport in place.
*
* Contract:
* - Preserves the selected device address (does not modify [currentDeviceAddressFlow]).
* - Preserves the `connectionRequested` gate; **MUST NOT** clear it. Safe to call concurrently with an explicit
* [disconnect] โ€” the internal gate check makes it a no-op in that case.
* - Safe to call when no transport is running โ€” implementations must no-op.
* - Does **NOT** bypass selected-device validation; the replacement transport is built from the same bonded address
* via the normal start path.
* - Emits ordinary transport-level transitions through the existing [RadioTransportCallback] surface, so observers
* see the transient [ConnectionState.DeviceSleep] state followed by [ConnectionState.Connected] when the
* replacement transport connects. (No [ConnectionState.Connecting] is emitted at the transport layer โ€” that is an
* app-level state set by [MeshConnectionManager], not a transport callback.)
*
* Suspends until the teardown/restart cycle completes.
*/
Tff7b72suspend Tff7b72fun Td2a8ffrestartTransportTb4b4b4(Tb4b4b4)

T8b949e/**
* Requests that the next BLE transport connection invalidates Android's GATT service cache before service
* discovery. Used after OTA firmware updates where the device reboots with a potentially different BLE service
* table on the same MAC address.
*
* The flag is one-shot: consumed on the first connect after being set.
*/
Tff7b72fun Td2a8ffrequestGattCacheInvalidationOnNextConnectTb4b4b4(Tb4b4b4)

T8b949e/**
* Consumes and returns the GATT cache invalidation request. Returns `true` exactly once after
* [requestGattCacheInvalidationOnNextConnect] was called, then resets to `false`.
*
* Intended to be called by the BLE transport during connection setup.
*/
Tff7b72fun Td2a8ffconsumeGattCacheInvalidationRequestTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean

T8b949e/** Returns the current device address. */
Tff7b72fun Td2a8ffgetDeviceAddressTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657String?

T8b949e/** Sets the device address to connect to. */
Tff7b72fun Td2a8ffsetDeviceAddressTb4b4b4(Te6edf3deviceAddrTb4b4b4: Tffa657String?Tb4b4b4)Tb4b4b4: Tffa657Boolean

T8b949e/** Constructs a full radio address for the specific interface type. */
Tff7b72fun Td2a8fftoInterfaceAddressTb4b4b4(Te6edf3interfaceIdTb4b4b4: Te6edf3InterfaceIdTb4b4b4, Te6edf3restTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Tffa657String

T8b949e/** Flow of user-facing connection error messages (e.g. permission failures). */
Tff7b72val Te6edf3connectionErrorTb4b4b4: Te6edf3FlowTff7b72<Tffa657StringTff7b72>

T8b949e/** The scope in which interface-related coroutines should run. */
Tff7b72val Te6edf3serviceScopeTb4b4b4: Te6edf3CoroutineScope
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.12s